package com.example.dingtalk.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.dingtalk.entity.dto.ExcelDto;
import com.example.dingtalk.entity.po.DingoaAccountsProcess;
import com.example.dingtalk.entity.po.DingoaSalesDetailProcess;
import com.example.dingtalk.entity.po.DingoaSalesProcess;
import com.example.dingtalk.mapper.DingoaSalesProcessMapper;
import com.example.dingtalk.service.ExpenseProcessHandler;
import com.example.dingtalk.service.IDingoaSalesDetailProcessService;
import com.example.dingtalk.service.IDingoaSalesProcessService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.dingtalk.util.TextConstants;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 销售平台费用流程表 服务实现类
 * </p>
 *
 * @author ckcool
 * @since 2024-08-08
 */
@Service
public class DingoaSalesProcessServiceImpl extends ServiceImpl<DingoaSalesProcessMapper, DingoaSalesProcess> implements IDingoaSalesProcessService, ExpenseProcessHandler {
    @Resource
    private IDingoaSalesDetailProcessService expensedetailService;


    /**
     * 处理数据保存
     *
     * @param instance
     * @param flag
     */
    @Override
    public void handle(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult instance, Boolean flag, String instanceId) throws JsonProcessingException, ParseException {
        LocalDate now = LocalDate.now();

        DingoaSalesProcess salesPlatformExpenseprocess = new DingoaSalesProcess();
        String title = instance.getTitle();
        //标题
        salesPlatformExpenseprocess.setTitle(title);
        //实例id
        salesPlatformExpenseprocess.setInstanceId(instanceId);
        //部门名
        salesPlatformExpenseprocess.setApplicantDepartment(instance.getOriginatorDeptName());
        //审批业务实例id 唯一的
        salesPlatformExpenseprocess.setVoucherColumn(instance.getBusinessId());
        // 截取标题
        salesPlatformExpenseprocess.setDebitSubject("销售费用");
        //申请人
        salesPlatformExpenseprocess.setApplicant(extractApplicantFromTitle(title));
        //拉取时间
        salesPlatformExpenseprocess.setFetchDate(new Date());

        String createTimeString = instance.getCreateTime();
        LocalDateTime localDateTime = LocalDateTime.parse(createTimeString, DateTimeFormatter.ISO_DATE_TIME);
        Date createTime = Date.from(localDateTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant());
        //创建时间
        salesPlatformExpenseprocess.setCreateTime(createTime);


        String finishTimeString = instance.getFinishTime();
        if(finishTimeString != null) {
            LocalDateTime localDate = LocalDateTime.parse(finishTimeString, DateTimeFormatter.ISO_DATE_TIME);
            Date finishTime = Date.from(localDate.atZone(ZoneId.of("Asia/Shanghai")).toInstant());
            //完成时间
            salesPlatformExpenseprocess.setFinishTime(finishTime);
        }

        //更新时间
        salesPlatformExpenseprocess.setUpdateTime(new Date());
        //实例id
        salesPlatformExpenseprocess.setInstanceId(instanceId);
        if (instance.getStatus().equals("COMPLETED")) {
            salesPlatformExpenseprocess.setIsComplete("已完成");
        } else {
            salesPlatformExpenseprocess.setIsComplete("待审批");
        }

        List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> componentValues = instance.getFormComponentValues();
        ObjectMapper objectMapper = new ObjectMapper(); // 用于 JSON 解析
        List<DingoaSalesDetailProcess> expenseDetails = new ArrayList<>();
        for (GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues componentValue : componentValues) {
            switch (componentValue.getName()) {
                case "付款事由":
                    salesPlatformExpenseprocess.setSummary(componentValue.getValue());
                    break;
                case "收款单位（个人）":
                    salesPlatformExpenseprocess.setRecipientName(componentValue.getValue());
                    break;
                case "收款人身份证号":
                    salesPlatformExpenseprocess.setRecipientIdNumber(componentValue.getValue());
                    break;
                case "收款单位（个人）账号":
                    salesPlatformExpenseprocess.setRecipientAccountNumber(componentValue.getValue());
                    break;
                case "收款单位（个人）开户行网点":
                    salesPlatformExpenseprocess.setReceivingBank(componentValue.getValue());
                    break;
                case "付款金额":
                    salesPlatformExpenseprocess.setCredit(new BigDecimal(componentValue.getValue()));
                    break;
                case "币种":
                case "币别":
                    salesPlatformExpenseprocess.setCurrency(componentValue.getValue());
                    break;
                case "付款公司":
                    if ("其他".equals(componentValue.getValue())) {
                        salesPlatformExpenseprocess.setPaymentBank("苏发国际");
                    } else {
                        salesPlatformExpenseprocess.setPaymentBank(componentValue.getValue());
                    }
                    break;
                case "费用类别明细":
                    // 解析费用类别明细的 JSON 字符串
                    String detailsJson = componentValue.getValue();
                    List<Map<String, Object>> detailsList = objectMapper.readValue(detailsJson, new TypeReference<List<Map<String, Object>>>() {
                    });

                    // 将解析后的明细保存到子表
                    for (Map<String, Object> detail : detailsList) {
                        DingoaSalesDetailProcess expenseDetail = new DingoaSalesDetailProcess();
                        List<Map<String, String>> rowValues = (List<Map<String, String>>) detail.get("rowValue");
                        for (Map<String, String> rowValue : rowValues) {
                            String label = rowValue.get("label");
                            String value = rowValue.get("value");
                            switch (label) {
                                case "平台":
                                    expenseDetail.setPlatform(value);
                                    break;
                                case "属地":
                                    expenseDetail.setRegion(value);
                                    break;
                                case "项目":
                                    expenseDetail.setProject(value);
                                    break;
                                case "店铺号":
                                    expenseDetail.setShopNumber(value);
                                    break;
                                case "listing负责人":
                                    expenseDetail.setListingResponsible(value);
                                    break;
                                case "费用分类":
                                    expenseDetail.setExpenseCategory(value);
                                    break;
                                case "备注":
                                    expenseDetail.setRemark(value);
                                    break;
                                case "付款金额":
                                    expenseDetail.setAmount(new BigDecimal(value));
                                    break;
                                default:
                                    break;
                            }
                        }
                        expenseDetails.add(expenseDetail);
                    }
                    break;
                default:
                    break;
            }
        }
        //保存主表
        this.save(salesPlatformExpenseprocess);
        for (DingoaSalesDetailProcess expenseDetail : expenseDetails) {
            expenseDetail.setSalesPlatformExpenseId(salesPlatformExpenseprocess.getId());
            expensedetailService.save(expenseDetail);
        }
    }

    /**
     * 根据标题提取申请人
     *
     * @param title
     * @return
     */
    private String extractApplicantFromTitle(String title) {
        Pattern pattern = Pattern.compile(TextConstants.PATTERN);
        Matcher matcher = pattern.matcher(title);
        if (matcher.find()) {
            return matcher.group(1);
        } else {
            throw new IllegalArgumentException("Cannot extract applicant from title: " + title);
        }
    }

    @Override
    public List<ExcelDto> toExcelDto(String startDate, String endDate,Boolean flag) {
        List<DingoaSalesProcess> expenseprocessList = null;
        // 构建基础查询
        LambdaQueryWrapper<DingoaSalesProcess> query = new LambdaQueryWrapper<DingoaSalesProcess>()
                .eq(DingoaSalesProcess::getIsComplete, "待审批")
                .ge(DingoaSalesProcess::getCreateTime, startDate)
                .le(DingoaSalesProcess::getCreateTime, endDate);
        if (!flag){
            query.eq(DingoaSalesProcess::getIsExporter, false);
        }
        expenseprocessList = this.list(query);
        List<DingoaSalesDetailProcess> expensedetails = expensedetailService.list();

        List<ExcelDto> excelDtos = new ArrayList<>();
        // 将子表记录按主表ID分组
        Map<Long, List<DingoaSalesDetailProcess>> detailMap = expensedetails.stream()
                .collect(Collectors.groupingBy(DingoaSalesDetailProcess::getSalesPlatformExpenseId));
        for (DingoaSalesProcess expenseprocess : expenseprocessList) {
            List<DingoaSalesDetailProcess> details = detailMap.get(expenseprocess.getId());
            if (details != null) {
                for (DingoaSalesDetailProcess expensedetail : details) {
                    ExcelDto excelDto = BeanUtil.copyProperties(expenseprocess, ExcelDto.class);
                    excelDto.setPaymentCompany(expenseprocess.getPaymentBank());
                    excelDto.setJournalProject(expenseprocess.getDebitSubject());
                    // 设置子表数据到ExcelDto中
                    excelDto.setAccountingDepartment(expensedetail.getRegion() + "-" + expensedetail.getPlatform());
                    excelDto.setProject(expensedetail.getProject());
                    excelDto.setAttributionDetails(expensedetail.getShopNumber() + "-" + expensedetail.getListingResponsible());
                    excelDto.setSummary(expensedetail.getExpenseCategory() + "-" + expenseprocess.getSummary());
                    excelDto.setCurrency(expenseprocess.getCurrency());
                    excelDto.setCredit(expensedetail.getAmount());

                    excelDtos.add(excelDto);
                }
            } else {
                // 如果主表记录没有对应的子表记录，也要创建ExcelDto对象
                ExcelDto excelDto = BeanUtil.copyProperties(expenseprocess, ExcelDto.class);
                excelDto.setPaymentCompany(expenseprocess.getPaymentBank());
                excelDto.setSummary(expenseprocess.getSummary());

                excelDtos.add(excelDto);
            }
            expenseprocess.setIsExporter(true);
        }
        updateBatchById(expenseprocessList);
        return excelDtos;
    }

    @Override
    public List<ExcelDto> toExcel(String startDate, String endDate,Boolean flag) {
        // 查询在指定日期范围内的数据并转换为 ExcelDto 列表
        // 假设 list() 方法会返回所有的 AccountsPayableprocess 对象
        List<DingoaSalesProcess> expenseprocessList = null;
        LambdaQueryWrapper<DingoaSalesProcess> query = new LambdaQueryWrapper<>();
        query.eq(DingoaSalesProcess::getIsComplete, "已完成");
        query.ge(DingoaSalesProcess::getCreateTime, startDate);
        query.le(DingoaSalesProcess::getCreateTime, endDate);
        if (!flag) {
            query.eq(DingoaSalesProcess::getIsExporter, false);
        }
        expenseprocessList = this.list(query);
        List<ExcelDto> excelDtos = new ArrayList<>();
        // 将子表记录按主表ID分组
        List<DingoaSalesDetailProcess> expensedetails = expensedetailService.list();
        Map<Long, List<DingoaSalesDetailProcess>> detailMap = expensedetails.stream()
                .collect(Collectors.groupingBy(DingoaSalesDetailProcess::getSalesPlatformExpenseId));
        for (DingoaSalesProcess expenseprocess : expenseprocessList) {
            List<DingoaSalesDetailProcess> details = detailMap.get(expenseprocess.getId());
            if (details != null) {
                for (DingoaSalesDetailProcess expensedetail : details) {
                    ExcelDto excelDto = BeanUtil.copyProperties(expenseprocess, ExcelDto.class);
                    excelDto.setPaymentCompany(expenseprocess.getPaymentBank());
                    excelDto.setJournalProject(expenseprocess.getDebitSubject());
                    // 设置子表数据到ExcelDto中
                    excelDto.setAccountingDepartment(expensedetail.getRegion() + "-" + expensedetail.getPlatform());
                    excelDto.setProject(expensedetail.getProject());
                    excelDto.setAttributionDetails(expensedetail.getShopNumber() + "-" + expensedetail.getListingResponsible());
                    excelDto.setSummary(expensedetail.getExpenseCategory() + "-" + expenseprocess.getSummary());
                    excelDto.setCurrency(expenseprocess.getCurrency());
                    excelDto.setCredit(expensedetail.getAmount());

                    excelDtos.add(excelDto);
                }
            } else {
                // 如果主表记录没有对应的子表记录，也要创建ExcelDto对象
                ExcelDto excelDto = BeanUtil.copyProperties(expenseprocess, ExcelDto.class);
                excelDto.setPaymentCompany(expenseprocess.getPaymentBank());
                excelDto.setSummary(expenseprocess.getSummary());
                excelDtos.add(excelDto);
            }
            expenseprocess.setIsExporter(true);
        }
        updateBatchById(expenseprocessList);
        return excelDtos;
    }
}
